package com.wechat.admin.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.Date;

/**
 * @Author:sjb
 * @CreateTime:2024-12-14
 * @Description: 生成和验证Jwt
 * @Version：1.0
 */
public class JwtUtil {

    // 生成密钥
    private static final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
    // Token有效期6小时
    private static final long EXPIRATION_TIME = 1000 * 60 * 60 * 6;

    /**
     * 生成Token
     * @param username
     * @return
     */
    public static String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
                .signWith(key)
                .compact();
    }

    /**
     * 验证Token
     * @param token
     * @return
     */
    public static Claims validateToken(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }

    /**
     * 验证JWT Token并与用户信息进行比对
     * @param token
     * @param userDetails
     * @return
     * @throws JwtException
     */
    public static Claims validateToken(String token, UserDetails userDetails) throws JwtException {
        try {
            // 解析Token
            Claims claims = Jwts.parserBuilder()
                    .setSigningKey(key)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();

            // 检查Token是否过期
            if (isTokenExpired(claims)) {
                throw new JwtException("Token已过期");
            }

            return claims;

        } catch (ExpiredJwtException e) {
            throw new JwtException("Token已过期", e);
        } catch (UnsupportedJwtException e) {
            throw new JwtException("不支持的Token格式", e);
        } catch (MalformedJwtException e) {
            throw new JwtException("Token格式不正确", e);
        } catch (SignatureException e) {
            throw new JwtException("Token签名无效", e);
        } catch (IllegalArgumentException e) {
            throw new JwtException("Token为空或解析失败", e);
        }
    }

    // 判断Token是否过期
    private static boolean isTokenExpired(Claims claims) {
        return claims.getExpiration().before(new Date());
    }

    /**
     * 刷新Token（可选，重新生成新的Token）
     * @param token 当前Token
     * @return 新的Token
     */
    public static String refreshToken(String token) {
        Claims claims = parseClaims(token);
        // 重新生成Token
        return generateToken(claims.getSubject());
    }

    /**
     * 解析JWT，提取Claims
     * @param token JWT Token
     * @return Claims
     */
    private static Claims parseClaims(String token) {
        return Jwts.parserBuilder()
                .setSigningKey(key)
                .build()
                .parseClaimsJws(token)
                .getBody();
    }


    /**
     * 从JWT中提取用户名
     * @param token JWT Token
     * @return 用户名
     */
    public static String extractUsername(String token) {
        return parseClaims(token).getSubject();
    }


}
